package com.ruoyi.lowcode.common;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.ruoyi.lowcode.database.DatabaseMain;
import com.ruoyi.lowcode.database.SourceFactory;
import com.ruoyi.lowcode.domain.LcField;
import com.ruoyi.lowcode.domain.LcModel;
import com.ruoyi.lowcode.domain.vo.LcDatabaseSourceVo;
import com.ruoyi.lowcode.domain.vo.LcDictionaryVo;
import com.ruoyi.lowcode.domain.vo.LcFieldVo;
import com.ruoyi.lowcode.domain.vo.LcModelVo;
import com.ruoyi.lowcode.mapper.LcDatabaseSourceMapper;
import com.ruoyi.lowcode.mapper.LcDictionaryMapper;
import com.ruoyi.lowcode.mapper.LcFieldMapper;
import com.ruoyi.lowcode.mapper.LcModelMapper;
import com.ruoyi.lowcode.sqlgenerator.GeneratorFactory;
import com.ruoyi.lowcode.sqlgenerator.GeneratorMain;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Component;

import java.util.*;

@Slf4j
@RequiredArgsConstructor
@Component
public class Lowcode {

    private final LcDatabaseSourceMapper databaseSourceMapper;

    private final LcDictionaryMapper dictionaryMapper;

    private final LcFieldMapper fieldMapper;

    private final LcModelMapper modelMapper;

    /**
     * 根据大屏元素配置获取相关数据
     *
     * @param modelId
     * @param exField
     * @param eyxField
     * @param eyyField
     * @return
     */
    public JSONObject getEchartsInfoByElementForScatterplot(Long modelId, Long exField, Long eyxField, Long eyyField) throws ClassNotFoundException {
        JSONObject data = new JSONObject();
        LcModelVo exModelVo = modelMapper.selectVoById(modelId);
        LcDatabaseSourceVo databaseSource = databaseSourceMapper.selectVoById(exModelVo.getDatabaseSourceId());
        GeneratorFactory generatorFactory = GeneratorMain.getGenerator(databaseSource.getType());
//        SourceFactory sourceFactory = DatabaseMain.getSource(databaseSource.getType());

//        Long[] fields = { exField, eyxField, eyyField };

//        List<LcFieldVo> queryFieldList = fieldMapper.selectVoList(
//                new QueryWrapper<LcField>().eq("model_id", modelId)
//                .eq("del_flag", "0")
//                .in("field_id", fields)
//        );

        LcFieldVo exFieldInfo = fieldMapper.selectVoById(exField);
        LcFieldVo eyxFieldInfo = fieldMapper.selectVoById(eyxField);
        LcFieldVo eyyFieldInfo = fieldMapper.selectVoById(eyyField);

        List<LcFieldVo> queryFieldList = Arrays.asList(exFieldInfo, eyxFieldInfo, eyyFieldInfo);

        String selectSql = generatorFactory.getSelectFieldSql(queryFieldList) + " " + generatorFactory.getSelectWhereSql(exModelVo.getSelectSql());
        System.out.println(selectSql.replace("#WHERESQL", "").toLowerCase());
        List<Map<String, Object>> dataList =
                DatabaseMain.getSource(databaseSource.getType()).selectList(databaseSource,
                        selectSql.replace("#WHERESQL", "").toLowerCase());

        List<List<Object>> seriesData = new ArrayList<>();

        for (Map<String, Object> info : dataList){
            List<Object> seriesDataInfo = Arrays.asList(
                    info.get(eyxFieldInfo.getFieldAlias()), info.get(eyyFieldInfo.getFieldAlias()), info.get(exFieldInfo.getFieldAlias()));
            seriesData.add(seriesDataInfo);
        }

        data.put("series", seriesData);

        return data;
    }

    /**
     * 根据大屏元素配置获取相关数据
     *
     * @param modelId
     * @param exField
     * @return
     */
    public JSONObject getEchartsInfoByElementForPie(Long modelId, Long exField) throws ClassNotFoundException {
        JSONObject data = new JSONObject();
        LcModelVo exModelVo = modelMapper.selectVoById(modelId);
        LcDatabaseSourceVo databaseSource = databaseSourceMapper.selectVoById(exModelVo.getDatabaseSourceId());
        GeneratorFactory generatorFactory = GeneratorMain.getGenerator(databaseSource.getType());
        SourceFactory sourceFactory = DatabaseMain.getSource(databaseSource.getType());
        LcFieldVo exFieldVo = fieldMapper.selectVoById(exField);
        fieldDictionary(exFieldVo);
        data.put("seriesName", exFieldVo.getRemark());
        List<JSONObject> seriesData = new ArrayList<>();

        String selectSql = generatorFactory.getCountFieldSql(exFieldVo.getFieldTableAliasName(), 0)
                + generatorFactory.getSelectWhereSql(exModelVo.getSelectSql());

        List<Map<String, Object>> dictionaryInfo = exFieldVo.getDictionaryInfo();
        for (Map<String, Object> info : dictionaryInfo){
            JSONObject seriesInfo = new JSONObject();

            List<Map<String, Object>> countList = sourceFactory.selectList(databaseSource,
                    selectSql.replace("#WHERESQL", "WHERE " + exFieldVo.getFieldTableAliasName() + " = '" + info.get("value") + "'"));

            if(countList.size() > 0 && ObjectUtils.isNotEmpty(countList.get(0).get("num"))){
                seriesInfo.put("value", countList.get(0).get("num"));
            }else {
                seriesInfo.put("value", 0);
            }
            seriesInfo.put("name", info.get("label"));
            seriesData.add(seriesInfo);
        }
        data.put("series", seriesData);
        return data;
    }

    /**
     * 根据大屏元素配置获取相关数据
     *
     * @param exField
     * @param eyData
     * @return
     */
    public JSONObject getEchartsInfoByElement(Long modelId, Long exField, String eyData) throws ClassNotFoundException {
        JSONObject data = new JSONObject();
        LcModelVo exModelVo = modelMapper.selectVoById(modelId);
        LcDatabaseSourceVo databaseSource = databaseSourceMapper.selectVoById(exModelVo.getDatabaseSourceId());
        GeneratorFactory generatorFactory = GeneratorMain.getGenerator(databaseSource.getType());
        SourceFactory sourceFactory = DatabaseMain.getSource(databaseSource.getType());
        LcFieldVo exFieldVo = fieldMapper.selectVoById(exField);
        fieldDictionary(exFieldVo);
        List<Object> yAxisData = new ArrayList<>();
        List<JSONObject> seriesData = new ArrayList<>();

        List<Map<String, Object>> dictionaryInfo = exFieldVo.getDictionaryInfo();
        for (Map<String, Object> info : dictionaryInfo){
            yAxisData.add(info.get("label"));
        }

        JSONArray eyFieldList = JSONArray.parseArray(eyData);
        for (Object obj : eyFieldList){
            JSONObject eyFieldData = JSONObject.parse(String.valueOf(obj));
            LcFieldVo eyFieldVo = fieldMapper.selectVoById(eyFieldData.getLong("eyField"));
            String selectSql = generatorFactory.getCountFieldSql(eyFieldVo.getFieldTableAliasName(), eyFieldData.getIntValue("statisticsType"))
                    + generatorFactory.getSelectWhereSql(exModelVo.getSelectSql());
            List<Object> series = new ArrayList<>();
            for (Map<String, Object> info : dictionaryInfo){
                List<Map<String, Object>> countList = sourceFactory.selectList(databaseSource,
                        selectSql.replace("#WHERESQL", "WHERE " + exFieldVo.getFieldTableAliasName() + " = '" + info.get("value") + "'"));

                if(countList.size() > 0 && ObjectUtils.isNotEmpty(countList.get(0).get("num"))){
                    series.add(countList.get(0).get("num"));
                }else {
                    series.add(0);
                }
            }

            JSONObject seriesInfo = new JSONObject();
            seriesInfo.put("name", eyFieldVo.getRemark());
            seriesInfo.put("data", series);

            seriesData.add(seriesInfo);
        }

        data.put("yAxis", yAxisData);
        data.put("series", seriesData);
        return data;
    }

    /**
     * 获取大屏元素模型详情
     *
     * @param modelId
     * @return
     */
    public List<LcModelVo> getModelById(Long modelId){
        List<LcModelVo> list = new ArrayList<>();
        list.add(modelMapper.selectVoById(modelId));
        return list;
    }

    /**
     * 获取大屏元素模型类别字段详情
     *
     * @param modelId
     * @return
     */
    public List<LcFieldVo> getFieldByModelIdAndDictionaryNotNull(Long modelId){
        List<LcFieldVo> fieldVoList = fieldMapper.selectVoList(
                new QueryWrapper<LcField>().eq("model_id", modelId)
                        .isNotNull("dictionary_id")
                        .eq("del_flag", "0")
        );
        return fieldVoList;
    }

    /**
     * 获取大屏元素模型字段详情
     *
     * @param modelId
     * @return
     */
    public List<LcFieldVo> getFieldByModelId(Long modelId){
        List<LcFieldVo> fieldVoList = fieldMapper.selectVoList(
                new QueryWrapper<LcField>().eq("model_id", modelId)
                        .eq("del_flag", "0")
        );
        return fieldVoList;
    }

    /**
     * 查询字段关联字典
     *
     * @param field
     */
    public void fieldDictionary(LcFieldVo field){
        if(field.getDictionaryId() != null && field.getDictionaryId() > 0){
            LcDictionaryVo dictionary = dictionaryMapper.selectVoById(field.getDictionaryId());
            if("0".equals(dictionary.getType())){ // JSON
                List<JSONObject> dataInfo = JSONArray.parseArray(dictionary.getContent(), JSONObject.class);
                List<Map<String, Object>> dictionaryInfo = new ArrayList<>();
                dataInfo.forEach( jsonObject -> {
                    dictionaryInfo.add(jsonObject);
                });
                field.setDictionaryInfo(dictionaryInfo);
            }

            if("1".equals(dictionary.getType())){
                LcDatabaseSourceVo databaseSource = databaseSourceMapper.selectVoById(dictionary.getDatabaseSourceId());
                try {
                    field.setDictionaryInfo(DatabaseMain.getSource(databaseSource.getType()).selectList(databaseSource, dictionary.getContent()));
                } catch (ClassNotFoundException e) {
                    log.error("字典" + dictionary.getDictionaryName() + "SQL执行查询失败。");
                }
            }
        }
    }

}
